#!/usr/bin/python

import socket,select,os
import struct,uuid,time
from helpFunc import *
from connbase import *
from streamc import *
import hashlib

class tcpRe(tcpReBase):
    def __init__(self,lp,salt):
        tcpReBase.__init__(self)        
        self.accepSock = s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)     
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind(('0.0.0.0',con_localPort))
        s.listen(500)    
        so = socket.socket()
        import threading    
        rate = con_minRate
        pushAhead = con_pushAhead
        packLimit = con_packLimit

        u = UStreamClient(lp,salt,rate,pushAhead,packLimit)
        t = threading.Thread(target=u.doWork)
        t.setDaemon(True)
        t.start()
        while True:
            try:
                so = socket.socket()
                add = ('127.0.0.1',u.listenPort)
                so.connect(add)    
                break
            except:
                pass
        print ('client starts')                 
        so.setblocking(0)        
        self.connSock=so

        while True:
            self.dowork()
            
    def dowork(self):   
        rl = [self.accepSock,self.connSock]
        if len(self.peerBuf)<self.peerBufMax:
            rl += self.getReadSocks()
     
        wl = self.getWriteSocks()
        if self.peerBuf:
            wl.append(self.connSock)
        
        el = []
        rl,wl,el = select.select(rl,wl,el,1)
        
        if self.accepSock in rl:
            csock, caddr = self.accepSock.accept()
            self.connNum += 1
            if self.connNum>self.maxNum:
                csock.close()
                self.connNum -= 1
                print ('too much',self.connNum)
            else:
                id = hashlib.md5(str(uuid.uuid1()).encode()).digest()
                msg = self.makeMsg(askConn_g,id,b'1')                
                print ("ask conn",self.connNum)
                csock.setblocking(0)
                self.idMap[id] = {'sock':csock}
                self.sendMsg(msg)
                
        for sock in rl:
            if  sock == self.accepSock:
                continue    
            if sock == self.connSock:
                ss = sock.recv(con_recLen)                
                msgList = self.dealData(sock, ss)
                for one in msgList:
                    self.decodeMsg(one)
                    ty = self.decodeType
                    id = self.decodeId
                    re = self.decodeData[0]
                    if  ty==connBack_g:
                        if re:
                            self.proxySocks[self.idMap[id]['sock']] = {'id':id,'data':b'','peerclose':False,
                                                                       'peerFull':False,'tellMyFull':False}
                            print ('askConnBack ok')
                            continue
                        self.idMap[id]['sock'].close()
                        del self.idMap[id]
                        self.connNum -= 1                        
                        print ('conn close',self.connNum)
                        continue
                    self.dealConnsockNormal(id,ty,self.decodeData)
                continue
            self.dealProxysocks(sock)
        for sock in wl:
            if sock == self.connSock:
                n = self.connSock.send(self.peerBuf)
                self.peerBuf = self.peerBuf[n:]
                continue
            self.dealWritesocks(sock)
            
if __name__ == '__main__':
    tcpRe(range(50000,50000+maxPortNum),b'salt')